package service

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strconv"
	v1 "ticket-proxy/api/ticketproxy/v1"
	"time"

	"github.com/go-kratos/kratos/v2/log"
)

type TicketService struct {
	v1.UnimplementedTicketServiceServer
	client    *http.Client
	targetURL string
	log       *log.Helper
}

func NewTicketService(logger log.Logger) *TicketService {
	return &TicketService{
		client: &http.Client{
			Transport: &http.Transport{
				MaxIdleConnsPerHost: 100, // 单机最大空闲连接数
				IdleConnTimeout:     100, // 空闲连接超时时间
			},
			Timeout: 10 * time.Second, // 单个请求的超时时间
		},
		targetURL: "http://localhost:8088",
		log:       log.NewHelper(logger),
	}
}

func (s *TicketService) GetTicket(ctx context.Context, req *v1.GetTicketRequest) (*v1.GetTicketResponse, error) {
	target := s.targetURL + "/ticket/" + strconv.Itoa(int(req.Id))
	resp, err := s.client.Get(target)
	if err != nil {
		s.log.Errorf("Failed request to %s, err: %v", target, err)
		return nil, err
	}
	defer resp.Body.Close()

	return parseResponse[v1.GetTicketResponse](resp, s.log)
}

func (s *TicketService) ListTickets(ctx context.Context, req *v1.ListTicketsRequest) (*v1.ListTicketsResponse, error) {
	httpReq, err := http.NewRequest("GET", s.targetURL+"/ticket", nil)
	if err != nil {
		return nil, err
	}

	// 解析 page 和 pageSize 参数，转成字符串
	query := httpReq.URL.Query()
	query.Add("page", strconv.Itoa(int(req.Page)))
	query.Add("pageSize", strconv.Itoa(int(req.PageSize)))
	httpReq.URL.RawQuery = query.Encode()

	resp, err := s.client.Do(httpReq)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var result struct {
		Data []*v1.GetTicketResponse `json:"data"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}
	return &v1.ListTicketsResponse{Tickets: result.Data}, nil
}

func (s *TicketService) UpdateTicket(ctx context.Context, req *v1.UpdateTicketRequest) (*v1.UpdateTicketResponse, error) {
	requestBody := map[string]interface{}{
		"id":  req.Id,
		"num": req.Num,
	}

	body, err := json.Marshal(requestBody)
	if err != nil {
		s.log.Errorf("Failed to marshal request body: %v", err)
		return nil, err
	}

	s.log.Infof("Sending request to: %s/ticket/%d", s.targetURL, req.Id)
	s.log.Infof("Request body: %s", string(body))

	httpReq, err := http.NewRequest("PUT", fmt.Sprintf("%s/ticket/%d", s.targetURL, req.Id), bytes.NewReader(body))
	if err != nil {
		s.log.Errorf("Failed to create HTTP request: %v", err)
		return nil, err
	}
	httpReq.Header.Set("Content-Type", "application/json")

	resp, err := s.client.Do(httpReq)
	if err != nil {
		s.log.Errorf("HTTP request failed: %v", err)
		return nil, err
	}
	defer resp.Body.Close()

	return parseResponse[v1.UpdateTicketResponse](resp, s.log)
}

// 解析响应结果 泛型函数
func parseResponse[T any](resp *http.Response, log *log.Helper) (*T, error) {
	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		log.Errorf("Request failed: %s", string(body))
		return nil, fmt.Errorf("internal server error: %s", string(body))
	}

	var result T
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}
	return &result, nil
}
